#include <cassert>
#include <cstdlib>
#include <cstdio>
#include <iostream>

#include <DigitalType.h>
#include <WaveformReaderForCompetition.h>


void getInputFile(int argc, const char** argv, std::string& inputFile) {
  for(int i = 1; i < argc; ++i) {
    if(argv[i][0] != '-') {
      inputFile = argv[i];
      break;
    }
  }
  assert(!inputFile.empty());
}

void getScopeInfo(Scope* scope) {
  assert(scope);
  // get  scope info.
  std::string scopeName = scope->name();
  std::string scopeType = scope->type();
  // scope vars.
  const std::map<std::string, std::string>& vars = scope->getVars();
  std::map<std::string, std::string>::const_iterator it;
  for (it = vars.cbegin(); it != vars.cend(); ++it) {
    std::string varName = (*it).first;
    std::string symbol = (*it).second;
    int type = scope->getSignalType(varName);
    int width = scope->getSignalBus(varName);
  }
  // get sub socpes info
  const std::vector<Scope*> &subscopes = scope->getSubScopes();
  for (unsigned i = 0; i < subscopes.size(); ++i) {
    getScopeInfo(subscopes[i]);
  }
}

void readDefinition(WaveformReaderForCompetition* reader) {
  assert(reader);
  std::vector<Scope*> tscopes;
  reader->topScopes(tscopes);
  for (unsigned i = 0; i < tscopes.size(); ++i) {
    getScopeInfo(tscopes[i]);
  }
}

void dumpScopeInfo(Scope* scope) {
  assert(scope);
  printf("scope %s %s\n", scope->type().c_str(), scope->name().c_str());
  const std::map<std::string, std::string>& vars = scope->getVars();
  std::map<std::string, std::string>::const_iterator it;
  for (it = vars.cbegin(); it != vars.cend(); ++it) {
    std::string varName = (*it).first;
    std::string symbol = (*it).second;
    int type = scope->getSignalType(varName);
    int width = scope->getSignalBus(varName);
    printf("var %s %s %d\n", symbol.c_str(), varName.c_str(), width);
  }
  // get sub socpes info
  const std::vector<Scope*> &subscopes = scope->getSubScopes();
  for (unsigned i = 0; i < subscopes.size(); ++i) {
    dumpScopeInfo(subscopes[i]);
  }
}

void readDataOfAllSignals(WaveformReaderForCompetition* reader) {
  assert(reader);
  std::vector<TimeValue*> tranTimes;
  reader->getAllTranValues(tranTimes);
  for (unsigned i = 0; i < tranTimes.size(); ++i) {
    long long t = tranTimes[i]->time();
    // var value in current time.
    const std::vector<Signal*>& sigValues = tranTimes[i]->allSignals();
    for (unsigned j = 0; j < sigValues.size(); ++j) {
      // var symbol ;
      std::string symbol = sigValues[j]->_symbol;
      // var value string; 1@ (sigle var);  b0100 ! (bus var);
      std::string valStr = sigValues[j]->_valStr;
      if (valStr.size() > 1)
        valStr += " ";
      valStr += symbol;
    }
  }
}

void readSelectedSignalData(WaveformReaderForCompetition* reader) {
  assert(reader);
  std::set<std::string> selectedSigs;
  selectedSigs.insert("\"");
  selectedSigs.insert("#");
  selectedSigs.insert("<");
  selectedSigs.insert("!");
  selectedSigs.insert("F");
  selectedSigs.insert("G");
  selectedSigs.insert("W");
  long long startTime = 0;
  long long endTime = 12000;
  std::map<long long, std::vector<std::string> > result;
  reader->readSignalDatas(selectedSigs, startTime, endTime, result);
  // tranverse result here.
}

void dumpVarTranDatas(WaveformReaderForCompetition* reader) {
  assert(reader);
  std::vector<TimeValue*> tranTimes;
  reader->getAllTranValues(tranTimes);
  for (unsigned i = 0; i < tranTimes.size(); ++i) {
    long long t = tranTimes[i]->time();
    printf("#%lld\n", t);
    const std::vector<Signal*>& sigValues = tranTimes[i]->allSignals();
    for (unsigned j = 0; j < sigValues.size(); ++j) {
      std::string valstr = sigValues[j]->_valStr;
      if (valstr.size() > 1)
        valstr += " ";
      valstr += sigValues[j]->_symbol;
      printf("%s\n", valstr.c_str());
    }
  }
}

void readAndDumpData(WaveformReaderForCompetition* reader, std::string outfile) {
  reader->dumpVCDFile(outfile);
  /*
  std::vector<Scope*> tscopes;
  reader->topScopes(tscopes);
  for (unsigned i = 0; i < tscopes.size(); ++i) {
    dumpScopeInfo(tscopes[i]);
  }
  if (dumpHeadOnly)
    return;
  dumpVarTranDatas(reader);
  */
}

int main(int argc, const char** argv) {
  std::string inputFile="test1.vcd";
  WaveformReaderForCompetition reader(inputFile);
  reader.read();
  if (false) { //dump也没啥用，不演示了
    std::string outfile = inputFile +".out";
    readAndDumpData(&reader, outfile);
  }
  /*else {
  // read definition.
  readDefinition(&reader);
  // Read all signals data.
  readDataOfAllSignals(&reader);

  // read selected signals data.
  readSelectedSignalData(&reader);
  }
  */
}
